﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Description;
using FANUC.DTO;

namespace FANUC.Controllers
{
    public class TodayAllRobotsStateDistributionController : ApiController
    {
        private FANUCDB db = new FANUCDB();

        [ResponseType(typeof(TodayAllRobotsStateDistributionDtoOutput))]
        public IHttpActionResult Get()
        {
            #region Test
            if (Helper.IsTest)
            {
                TodayAllRobotsStateDistributionDtoOutput testData = new TodayAllRobotsStateDistributionDtoOutput();
                testData.Date = System.DateTime.Now;

                testData.RunningtRatio = 75.5M;
                testData.PowerOffRatio = 10M;
                testData.FaultRatio = 7.5M;
                testData.ReadyRatio = 7M;

                return Ok(testData);
            }
            #endregion

            DateTime today0 = System.DateTime.Now.Date;
            DateTime now = System.DateTime.Now;
            var robots = db.Robot.ToList();
            List<TodayRobotStateDistributionDtoOutput> allStateDistribution = new List<TodayRobotStateDistributionDtoOutput>();
            foreach (var robot in robots)
            {
       
                //此机器人当天第一个状态;-1:default,1:PowerOff,2:Fault,3:Ready,4:Running
                int firstState, lastState = -1;
                //第一次发生事件改变的时间点
                DateTime todayFirstChangeTime;
    

                //此机器人当天0点开始第一个变化记录，FANUC会在0点插入一条最新机器人的状态
                var todayFirstChangeRecord = db.Robot_State_Change_History.Where(a => a.ChangeDateTime >= today0 && a.Robot_ID == robot.ID).OrderBy(a => a.ChangeDateTime).FirstOrDefault();
                if (todayFirstChangeRecord == null)
                {
                    todayFirstChangeTime = today0;
                    firstState = 1;
                }
                else
                {
                    todayFirstChangeTime = todayFirstChangeRecord.ChangeDateTime;
                    firstState = todayFirstChangeRecord.Changed_State_Type;
                }

                List<Robot_State_Change_History> allStateChangeRecords = db.Robot_State_Change_History.Where(a => a.ChangeDateTime > todayFirstChangeTime && a.Robot_ID == robot.ID).ToList();
                //按状态合计各状态时间(分钟)
                var stateGroupSumByState = from a in allStateChangeRecords group a by new { a.Original_State_Type } into grp select new { grp.Key.Original_State_Type, TotalMinutes = grp.Sum(a => a.Period)/60 };

                //获取当天最后一个机器人状态
                var todayLastChangeRecord = db.Robot_State_Change_History.Where(a => a.ChangeDateTime > today0 && a.Robot_ID == robot.ID).OrderByDescending(a => a.ChangeDateTime).FirstOrDefault();
                DateTime lastChangeTime;
                if (todayLastChangeRecord == null)
                {
                    lastState = 1;
                    lastChangeTime = now;
                }
                else
                {
                    lastState = todayLastChangeRecord.Changed_State_Type;
                    lastChangeTime = todayLastChangeRecord.ChangeDateTime;
                }

                int todayTotalMinutes = Convert.ToInt16((now - today0).TotalMinutes);

                var todayTotalRunningSum = stateGroupSumByState.Where(a => a.Original_State_Type == 4).FirstOrDefault();
                int todayTotalRunningMinutes = Convert.ToInt16(todayTotalRunningSum == null ? 0 : todayTotalRunningSum.TotalMinutes) + (lastState == 4 ? Convert.ToInt16((now - lastChangeTime).TotalMinutes) : 0);
                decimal runningRatio = Convert.ToDecimal(todayTotalRunningMinutes) / todayTotalMinutes;

                var todayTotalReadySum = stateGroupSumByState.Where(a => a.Original_State_Type == 3).FirstOrDefault();
                int todayTotalReadyMinutes = Convert.ToInt16(todayTotalReadySum == null ? 0 : todayTotalReadySum.TotalMinutes) + (lastState == 3 ? Convert.ToInt16((now - lastChangeTime).TotalMinutes) : 0);
                decimal readyRatio = Convert.ToDecimal(todayTotalReadyMinutes) / todayTotalMinutes;

                var todayTotalFaultSum = stateGroupSumByState.Where(a => a.Original_State_Type == 2).FirstOrDefault();
                int todayTotalFaultMinutes = Convert.ToInt16(todayTotalFaultSum == null ? 0 : todayTotalFaultSum.TotalMinutes) + (lastState == 2 ? Convert.ToInt16((now - lastChangeTime).TotalMinutes) : 0);
                decimal faultRatio = Convert.ToDecimal(todayTotalFaultMinutes) / todayTotalMinutes;

                decimal powerOffRatio = 1 - runningRatio - readyRatio - faultRatio;

                TodayRobotStateDistributionDtoOutput stateDistribution = new TodayRobotStateDistributionDtoOutput();
                stateDistribution.RunningtRatio = decimal.Round(runningRatio, 4);
                stateDistribution.FaultRatio = decimal.Round(faultRatio, 4);
                stateDistribution.ReadyRatio = decimal.Round(readyRatio, 4);
                stateDistribution.PowerOffRatio = decimal.Round(powerOffRatio, 4);
                allStateDistribution.Add(stateDistribution);
            }
            decimal totalRunningRatio = 0;
            decimal totalPowerOffRatio = 0;
            decimal totalFaultRatio = 0;
            decimal totalReadyRatio = 0;
            TodayAllRobotsStateDistributionDtoOutput data = new TodayAllRobotsStateDistributionDtoOutput();
            data.Date = today0;
            foreach (var ratio in allStateDistribution)
            {
                totalRunningRatio += ratio.RunningtRatio;
                totalPowerOffRatio += ratio.PowerOffRatio;
                totalFaultRatio += ratio.FaultRatio;
                totalReadyRatio += ratio.ReadyRatio;
            }
            data.RunningtRatio = decimal.Round(totalReadyRatio * 100 / (100 * allStateDistribution.Count()), 4);
            data.PowerOffRatio = decimal.Round(totalPowerOffRatio * 100 / (100 * allStateDistribution.Count()), 4);
            data.FaultRatio = decimal.Round(totalFaultRatio * 100 / (100 * allStateDistribution.Count()), 4);
            data.ReadyRatio = decimal.Round(totalReadyRatio * 100 / (100 * allStateDistribution.Count()), 4);

            return Ok(data);
        }

        [ApiExplorerSettings(IgnoreApi = true)]
        public string Options()
        { return null; }
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}
